//
//  ViewController.m
//  NSThread(多线程01)
//
//  Created by 吴志勇 on 2020/3/5.
//  Copyright © 2020 wzy. All rights reserved.
//

#import "ViewController.h"
#import "TestOpertion.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //1.获得主线程
    NSThread *mainThread = [NSThread mainThread];
    
    //2.获得当前线程
    NSThread *currentThread = [NSThread currentThread];
    
    //3.判断主线程
    //3.1 number = 1
    //3.2类方法
    BOOL isMainThread = [NSThread isMainThread];
    //3.3对象方法
    BOOL isMainThreadbB = [currentThread isMainThread];
    
}


- (void)UseNSThread{
    //线程的生命周期:当线程任务完成，线程结束
   /*
    第一个参数:目标对象  self
    第二个参数:方法选择器 调用的方法
    第三个参数:前面调用方法的参数
    */
 
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"abc"];
    thread.name = @"线程A";
    //线程的优先级0.0~1.0之间 1.0最高
    thread.threadPriority = 0.1;
    [thread start];
    
    
    
}

- (void)run:(NSString *)param{
    
    
    //阻塞线程
//    [NSThread sleepForTimeInterval:2.0];
//    [NSThread exit];//退出线程
    //token:锁 必须是全局唯一的，一般用self
    //1.注意加锁的位置
    //2.注意加锁的前提条件，多线程共享同一块资源
    //3.加锁需要耗费性能
    //4.加锁的结果:线程同步
//    @synchronized (self) {
//        NSLog(@"----");
//    }
//    CFTimeInterval start = CFAbsoluteTimeGetCurrent();//获取当前绝对时间
}


- (void)useGCD{
    //同步:主要在当前线程中执行任务，不具备开启新线程的能力
    //异步:主要在新的线程中执行任务，具备开启新线程的能力
    //并发:允许多个任务并发(同时)进行
    //串行:一个任务执行完毕后，再执行下一个任务
    
    //异步函数+并发队列:会开启多条线程，队列中的任务是异步执行的
    //第一个参数:C语言的字符串，标签
    //第二个参数:队列的类型 DISPATCH_QUEUE_CONCURRENT:并发 DISPATCH_QUEUE_SERIAL_INACTIVE:串行
    
//   dispatch_queue_t queue =  dispatch_queue_create("这是一个标签", DISPATCH_QUEUE_CONCURRENT);
//
//    dispatch_async(queue, ^{
//        NSLog(@"---");
//    });
    
    
}

 //异步函数+并发队列:会开启多条线程，队列中的任务是异步执行的
- (void)asyncConcurrent{
   
    //第一个参数:C语言的字符串，标签
    //   dispatch_queue_t queue =  dispatch_queue_create("这是一个标签", DISPATCH_QUEUE_CONCURRENT);
    //
    //    dispatch_async(queue, ^{
    //        NSLog(@"---");
    //    });
}


//异步函数+串行队列:开启一条线程，队列中的任务是串行执行的
- (void)asyncSerial{
    
    dispatch_queue_t queue =  dispatch_queue_create("这是一个标签", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(queue, ^{
        NSLog(@"---");
    });
}

//同步函数+并发队列:不会开启新线程，队列中的任务是串行的
- (void)syncConcurretn{
    
       dispatch_queue_t queue =  dispatch_queue_create("这是一个标签", DISPATCH_QUEUE_CONCURRENT);
    
        dispatch_sync(queue, ^{
            NSLog(@"---");
        });
}

//同步函数+串行队列:不会开启线程，队列中的任务是串行执行的
- (void)syncSerial{
//    dispatch_queue_t queue =  dispatch_queue_create("这是一个标签", DISPATCH_QUEUE_SERIAL);
//
//    dispatch_sync(queue, ^{
//        NSLog(@"---");
//    });
}

////同步函数+主队列：所有任务都在主线程执行，不会开线程
- (void)asyncMain{
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        NSLog(@"0000");
    });
}


//同步函数+主队列：死锁
- (void)syncMain{
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        NSLog(@"0000");
    });
    //主队列特点：如果主队列发现当前主线程有任务再执行，那么主队列会暂停调用队列中的任务，主导主线程空闲为止
}


//barrier 栅栏函数
- (void)barrierAsync{
    //栅栏函数不能使用全局并发队列
    dispatch_queue_t queue = dispatch_queue_create("we", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });
    
    dispatch_barrier_sync(queue, ^{
        NSLog(@"这是一个栅栏");
    });
    dispatch_async(queue, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });
}
//快速迭代:开子线程和主线程一起完成遍历任务，任务的执行是并发的
- (void)applyDemo{
    dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index) {
        NSLog(@"%ld------%@",index,[NSThread currentThread]);
    });
}



//队列组
- (void)group{
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
        NSLog(@"1------%@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"2------%@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"3------%@",[NSThread currentThread]);
    });
    
    //拦截通知，当队列中搜有的任务都执行完毕的时候会进入到下面的方法
    //该方法本身是异步的
//    dispatch_group_notify(group, queue, ^{
//        NSLog(@"任务结束");
//    });
    
    //在该方法后面的异步任务会纳入到队列组的监听范围进入群组
    dispatch_group_enter(group);
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"3------%@",[NSThread currentThread]);
        dispatch_group_leave(group);
    });
    
    //等待，死等，直到队列中所有的任务都执行完毕后才能执行
    //阻塞
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}

//NSOpertion
- (void)useSelfOpertion{
    TestOpertion *op1 = [[TestOpertion alloc] init];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:op1];
}

//NSOpertion的其他用法
- (void)otherNSOpertion{
    //创建队列
   //   默认是并发队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
//    设置最大并发数量 maxConcurrentOperationCount
//    同一时间最多有多少个任务
//    串行执行任务 !=只开一条线程(线程同步)
//   maxConcurrentOperationCount >1 并发队列
//   maxConcurrentOperationCount ==1 串行队列
//   maxConcurrentOperationCount ==0 不会执行任务
    queue.maxConcurrentOperationCount = 5;
    NSBlockOperation *op1= [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1");
    }];
    NSBlockOperation *op2= [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"2");
    }];
    NSBlockOperation *op3= [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"3");
    }];
    NSBlockOperation *op4= [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"4");
    }];
    //依赖，不要循环依赖
    [op1 addDependency:op2];
    
    
    
    
    //监听执行完毕
    [op1 setCompletionBlock:^{
        
    }];
    
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
    [queue addOperation:op4];
    
    //队列暂停，是可以恢复的，不能暂停当前正在执行状态的任务
    [queue setSuspended:YES];
    //继续执行
    [queue setSuspended:NO];
    
    //取消，不可以恢复
    [queue cancelAllOperations];
}


//保存文件到内存缓存
- (void)saveFile{
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *fileName = @"text";
    NSString *fullPath = [caches stringByAppendingPathComponent:fileName];
    [[NSData data] writeToFile:fullPath atomically:YES];
    
    NSData *data = [NSData dataWithContentsOfFile:fullPath];
    UIImage *image = [UIImage imageWithData:data];
    

}

@end
